#pragma once

#include "noncopyable.h"
#include "InetAddress.h"
#include "Callbacks.h"
#include "Buffer.h"
#include "Timestamp.h"
#include "Logger.h"

#include <memory>
#include <string>
#include <atomic>

class Channel;
class EventLoop;
class Socket;

/**
 * @brief Acceptor accept 获得connfd -> 封装TcpConnection ->设置Channel回调 ->注册到Poller上 -> Channel 执行回调
 *
 */
class TcpConnection : noncopyable, public std::enable_shared_from_this<TcpConnection> // 可以在函数中进行传递共享指针
{
public:
    TcpConnection(EventLoop *loop, const std::string &nameArg, int sockfd, const InetAddress &localAddr, const InetAddress &peerAddr);
    ~TcpConnection();

    EventLoop *getLoop() const
    {
        return loop_;
    }
    const std::string &name() const
    {
        return name_;
    }
    const InetAddress &localAddrress() const
    {
        return localAddr_;
    }
    const InetAddress &peerAddress() const
    {
        return peerAddr_;
    }

    bool connected() const
    {
        return state_ == kConnected;
    }

    void send(const std::string &buff);

    void shutdown();

    void connectEstablished();

    void connectDestoryed();

    // TcpConnection回调
    void setConnectionCallback(const ConnectionCallback &cb)
    {
        connectionCallback_ = cb;
    }
    void setMessageCallback(const MessageCallback &cb)
    {
        messageCallback_ = cb;
    }
    void setWriteCompleteCallback(const WriteCompleteCallback &cb)
    {
        writeCompleteCallback_ = cb;
    }
    void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, size_t highWaterMark)
    {
        highWaterMarkCallback_ = cb;
        highWaterMark_ = highWaterMark;
    }
    void setCloseCallback(const CloseCallback &cb)
    {
        closeCallback_ = cb;
    }

private:
    enum StateE
    {
        kDisconnected,
        kConnecting,
        kConnected,
        kDisconnecting
    };
    void setState(StateE state)
    {
        LOG_INFO("TcpConnection state form %d to %d\n", (int)state_, (int)state);
        state_ = state;
    }
    // event回调函数
    void handleRead(Timestamp receiveTime);
    void handleWrite();
    void handleClose();
    void handleError();

    void sendInLoop(const void *message, size_t len);
    void shutdownInLoop();

    EventLoop *loop_;
    const std::string name_;
    std::atomic_int state_;
    bool reading_;
    // socket&channel
    std::unique_ptr<Socket> socket_;
    std::unique_ptr<Channel> channel_;
    // ip&port 信息
    const InetAddress localAddr_;
    const InetAddress peerAddr_;
    // TcpConnection回调函数
    ConnectionCallback connectionCallback_;
    MessageCallback messageCallback_;
    WriteCompleteCallback writeCompleteCallback_;
    HighWaterMarkCallback highWaterMarkCallback_;
    CloseCallback closeCallback_;
    size_t highWaterMark_;
    // 接收&发送缓冲区
    Buffer inputBuffer_;
    Buffer outputBuffer_;
};